<?php
if (!defined('__COLA_DIR__')) exit;

/**
 * 基本设置组件
 *
 * @author edikud
 * @package Widget
 * @copyright Copyright (c) 2019 Cola (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */
class Widget_Options_Permalink extends Widget_Abstract_Options implements Widget_Interface_Do
{
    /**
     * 数据库中的路由数据
     *
     * @access private
     * @var array
     */
    private $_routingTable = array();

    public function __construct($request, $response, $params = NULL)
    {
        parent::__construct($request, $response, $params);
        $this->_routingTable = $this->options->routingTable;
    }
    /**
     * 执行函数
     *
     * @access public
     * @return void
     */
    public function execute()
    {
		$this->user->pass('admin');
    }

    /**
     * 检验规则是否冲突
     *
     * @access public
     * @param string $value 路由规则
     * @return boolean
     */
    public function checkRule($value, $pkey)
    {
        $routingTable = $this->_routingTable;
        $currentTable = array('custom' => array('url' => $this->encodeRule($value)));
        $parser = new Router_Parser($currentTable);
        $currentTable = $parser->parse();
        $regx = $currentTable['custom']['regx'];

		unset($routingTable[0]);
		unset($routingTable[$pkey]);
		unset($routingTable['post']);
		unset($routingTable['page']);
		
        foreach ($routingTable as $key => $val) {
			$pathInfo = $this->decodeRule($val['url']);
			if (FALSE !== strpos($pathInfo, '{')) {
                $pathInfo = str_replace(
			        array('{cid}', '{alias}', '{category}', '{year}', '{month}', '{day}', '{', '}'),
                    array('123', 'hello', 'default', '2008', '08', '08', '', ''), $pathInfo);

                if (preg_match($regx, $pathInfo)) {
                    return false;
                }
			}
        }
        return true;
    }
	
    /**
     * 修改路由
     */
    public function edit()
    {
		$form = $this->form();
		
		/** 验证格式 */
        if ($message = $form->validate()) {
            $this->result->set(key($message), current($message));
        }

        $settings = defined('__COLA_REWRITE__') ? array() : $this->request->from('rewrite');

        $modified = false;
		$routings = $this->request->from(array_keys($_POST));
        foreach ($this->_routingTable as $key => &$value) 
		{
            if (isset($routings[$key])) {
                $value['url'] = $this->encodeRule($routings[$key]);
                $modified = true;
            }
        }

		if ($modified) {
            if (isset($this->_routingTable[0])) {
                unset($this->_routingTable[0]);
            }
			$settings['routingTable'] = serialize($this->_routingTable);
		}
		
        foreach ($settings as $name => $value) 
		{
            $this->update($name, $value);
        }
		
        if ($modified) {
			$this->options->__set('rewrite', !!$this->request->rewrite);
			
			!$this->request->rewrite && File::unlink(__COLA_DIR__ . '/.htaccess');
			
            $this->result->set(0, _t("路由变更已经保存"), array('location'=>$this->options->ucenterUrl('options-permalink', false)));

        } else {
            $this->result->set(-1, _t("路由未变更"));
        }
    }

    /**
     * 编码自定义的路径
     *
     * @access private
     * @param string $rule 待编码的路径
     * @return string
     */
    protected function encodeRule($rule)
    {
        return str_replace(array('{cid}', '{alias}', '{category}', '{directory}', '{year}', '{month}', '{day}', '{mid}', '{', '}'),
            array('[cid:digital]', '[alias]', '[category]', '[directory:split:0]',
                '[year:digital:4]', '[month:digital:2]', '[day:digital:2]', '[mid:digital]', '[', ']'), $rule);
    }
    /**
     * 解析自定义的路径
     *
     * @access private
     * @param string $rule 待解码的路径
     * @return string
     */
    protected function decodeRule($rule)
    {
        return preg_replace("/\[([_a-z0-9-]+)[^\]]*\]/i", "{\\1}", $rule);
    }
    /**
     * 检查checkContentsPattern里是否含有必要参数
     * 
     * @param mixed $value 
     * @access public
     * @return void
     */
    public function checkContentsPattern($value)
    {
        return strpos($value, '{alias}') !== false || strpos($value, '{cid}') !== false;
    }
	
    /**
     * 检查checkAuthorPattern里是否含有必要参数
     * 
     * @param mixed $value 
     * @access public
     * @return void
     */
    public function checkAuthorPattern($value)
    {
        return strpos($value, '{uid}') !== false || strpos($value, '{name}') !== false;
    }

    /**
     * 检查categoryPattern里是否含有必要参数
     * 
     * @param mixed $value 
     * @access public
     * @return void
     */
    public function checkCategoryPattern($value)
    {
        return strpos($value, '{alias}') !== false || strpos($value, '{mid}') !== false || strpos($value, '{directory}') !== false;
    }
	
    /**
     * 检测是否可以rewrite
     *
     * @access public
     * @param string $value 是否打开rewrite
     * @return void
     */
    public function ajaxRewrite()
    {
		$hasWrote = file_exists(__COLA_DIR__ . '/.htaccess');
		
		if (!$hasWrote && File::is_writable(__COLA_DIR__)){
		
            $parsed = parse_url($this->options->siteUrl);
            $basePath = empty($parsed['path']) ? '/' : $parsed['path'];
            $basePath = rtrim($basePath, '/') . '/';
		    $apache = '<IfModule mod_rewrite.c>'."\r\n";
		    $apache .= 'RewriteEngine On'."\r\n";
		    $apache .= 'RewriteBase '. $basePath ."\r\n";
		    $apache .= 'RewriteCond %{REQUEST_FILENAME} !-f'."\r\n";
		    $apache .= 'RewriteCond %{REQUEST_FILENAME} !-d'."\r\n";
		    $apache .= 'RewriteRule ^(.*)$ ' . $basePath . 'index.php [L]'."\r\n";
		    $apache .= '</IfModule>';
		
		    $hasWrote = File::write(__COLA_DIR__ . '/.htaccess', $apache);
		}
		
        /** 设置提示信息 */
        $this->result->set(
			$hasWrote ? 0 : 1, 
			$hasWrote ? '' : _t('我们检测到你使用了apache服务器, 但是程序无法在根目录创建.htaccess文件, 这可能是产生这个错误的原因.') . _t('请调整你的目录权限, 或者手动创建一个.htaccess文件.')
		);
    }
	
    /**
     * 输出表单结构'/action/options-permalink'
     *
     * @access public
     * @return Form
     */
    public function form()
    {
        /** 构建表格 */
        $form = new Form($this->security->actionUrl('options-permalink?edit', false), 'rewrite-');

        /** 是否使用地址重写功能 */
        $rewrite = new Form_Radio('rewrite', array('0' => _t('不启用'), '1' => _t('启用')),
        $this->options->rewrite, _t('是否使用地址重写功能'), _t('地址重写即 rewrite 功能是某些服务器软件提供的优化内部连接的功能.') . '<br />'
        . _t('打开此功能可以让你的链接看上去完全是静态地址.')); 

        $form->addInput($rewrite);
		
        /** 如果是apache服务器, 可能存在无法写入.htaccess文件的现象 */
        if ((isset($_SERVER['SERVER_SOFTWARE']) && false !== strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache'))
            || function_exists('apache_get_version')) {
				
			if(File::is_writable(__COLA_DIR__)) {
                $this->widget('Widget_Scripts')->set("
                $(document).ready(function () {
				    var jform = $(\".rewrite-form\");	
				    jform.on('click', 'input[type=\"radio\"][name=\"rewrite\"][value=\"1\"]', function() {
                        $.ajax({
		                    url: '".$this->security->actionUrl('options-permalink?ajax', false)."',
		                    success: function(s){
			                    if(!s) return $.alert('Server Response Empty!');
		                        if(s.code == 0) {
                                    $.ajax({
		                                url: '".Router::url('do', array('action'=>'ajax?rewrite'), $this->options->siteUrl)."',
		                                success: function(s){
			                                if(!s) return $.alert('Server Response Empty!');
		                                    if(s != 'OK') {
			                                    $.alert(s);
		                                    }
		                                },
			                            error: function() {
				                            $.alert('" . _t('重写功能检测失败, 请检查你的服务器设置') . "', null, 3500);
			                            },
                                    });	
		                        } else {
			                        $.alert(s.msg);
		                        }
		                    },
                        });
				    });	
				    jform.ajaxSubmit();
	            });");

			}else{
				
			    $form->set('<small class="text-danger">' . _t('请调整你的目录权限, 或者手动创建一个.htaccess文件.') . '</small><br>');
			}
        } else {
			
			$form->set('<small class="text-danger">' ._t('友情提示：您的服务器为 %s 需要手动配置开启 URL-REWRITE.', $this->request->getServer('SERVER_SOFTWARE')) . '</small><br><br>');
		}

        /** 自定义文章路径 */
        $post = new Form_Text('post', NULL, $this->decodeRule($this->options->routingTable['post']['url']), _t('自定义文章路径'), _t('可用参数: <code>{cid}</code> 文章 ID, <code>{alias}</code> 文章缩略名, <code>{category}</code> 分类, <code>{directory}</code> 多级分类.')
            . '<br />' . _t('请在路径中至少包含上述 {cid} {alias} 中的一项参数.'));
        $form->addInput($post);
		
        /** 自定义独立页面路径 */
        $page = new Form_Text('page', NULL, $this->decodeRule($this->options->routingTable['page']['url']), _t('独立页面路径'), _t('可用参数: <code>{cid}</code> 页面 ID, <code>{alias}</code> 页面缩略名')
            . '<br />' . _t('请在路径中至少包含上述 {cid} {alias} 中的一项参数.'));
        $form->addInput($page);

        /** 分类页面 */
        $category = new Form_Text('category', NULL, $this->decodeRule($this->options->routingTable['category']['url']), _t('分类路径'), _t('可用参数: <code>{mid}</code> 分类 ID, <code>{alias}</code> 分类缩略名, <code>{directory}</code> 多级分类')
            . '<br />' . _t('请在路径中至少包含上述 {mid} {alias} {directory} 中的一项参数.'));
        $form->addInput($category);
		
        /** 标签页面 */
        $tag = new Form_Text('tag', NULL, $this->decodeRule($this->options->routingTable['tag']['url']), _t('标签路径'), _t('可用参数: <code>{mid}</code> 标签 ID, <code>{alias}</code> 标签缩略名')
            . '<br />' . _t('请在路径中至少包含上述 {mid} {alias} 中的一项参数.'));
        $form->addInput($tag);		
		
        /** 用户页面 */
        $author = new Form_Text('author', NULL, $this->decodeRule($this->options->routingTable['author']['url']), _t('用户路径'), _t('可用参数: <code>{uid}</code> 用户 ID, <code>{name}</code> 用户名')
            . '<br />' . _t('请在路径中至少包含上述 {uid} {name} 中的一项参数.'));
        $form->addInput($author);

        /** 提交按钮 */
        $submit = new Form_Submit('submit', NULL, _t('保存设置'));
        $form->set($submit);

		$post->addRule(array($this, 'checkContentsPattern'), _t('自定义文章路径中没有包含 {cid} 或者 {alias} '));
		$page->addRule(array($this, 'checkContentsPattern'), _t('独立页面路径中没有包含 {cid} 或者 {alias} '));
		$category->addRule(array($this, 'checkCategoryPattern'), _t('分类路径中没有包含 {mid} 或者 {alias} '));
		$tag->addRule(array($this, 'checkCategoryPattern'), _t('标签路径中没有包含 {mid} 或者 {alias} '));
		$author->addRule(array($this, 'checkAuthorPattern'), _t('用户路径中没有包含 {uid} 或者 {name} '));

		/** 插件接口 */
		//HOOK PLUG_Options_Permalink_Form($form, $this);
		
        $inputs = $form->getInputs();
        foreach ($inputs as $key => $val) {
            $form->getInput($key)->addRule(array($this, 'checkRule'), _t('链接与现有规则存在冲突! 它可能影响解析效率, 建议你重新分配一个规则.'), $key);
        }
		
        return $form;
    }

    /**
     * 绑定动作
     *
     * @access public
     * @return void
     */
    public function action(){
		$this->security->protect();
        $this->on($this->request->is('edit'))->edit();
        $this->on($this->request->is('ajax'))->ajaxRewrite();
		$this->result->set(404, _t('请求的资源不存在'));
    }
}
